package cn.lena.hadoop.HDFS;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.junit.Test;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * HDFS的API操作
 * @author lena
 * @date 2021/5/16
 */
public class API {

	/**
	 * 文件上传
	 * 上传本地文件到hdfs服务器上
	 */
	@Test
	public void copyFromLocalFile() throws IOException,InterruptedException,URISyntaxException {

		// 获取fs对象
		Configuration conf=new Configuration();
		//TODO:第一个的参数应为真实的服务器信息，第三个参数应为真实服务器用户
		FileSystem fs= FileSystem.get(new URI("hdfs://hadoop102:9000"),conf,"atguigu");

		// 执行上传操作
		//TODO:第一个路径是本地文件的路径，第二个路径是要上传的服务器路径
		fs.copyFromLocalFile(new Path("e:/test.txt"),new Path("/test.txt"));

		// 关闭资源
		fs.close();

	}

	/**
	 * 文件下载
	 * 将hdfs上的文件下载到本地
	 */
	@Test
	public void copyToLocalFile() throws IOException,InterruptedException,URISyntaxException{

		// 获取fs对象
		Configuration conf=new Configuration();
		//TODO:第一个的参数应为真实的服务器信息，第三个参数应为真实服务器用户
		FileSystem fs= FileSystem.get(new URI("hdfs://hadoop102:9000"),conf,"atguigu");

		// 执行下载操作
		//方式一：TODO:第一个路径是在服务器上的源文件路径，第二个路径是要下载到的本地路径
		fs.copyToLocalFile(new Path("/test.txt"),new Path("e:/test.txt"));
		//方式二：TODO:第一个参数表示是否删除原数据，第二三个参数与方式一一致，第四个参数表示是否是本地模式（涉及安全校验问题）
		//fs.copyToLocalFile(false,new Path("/test.txt"),new Path("e:/test.txt"),true);

		// 关闭资源
		fs.close();

	}

	/**
	 * 删除文件、文件夹
	 */
	@Test
	public void delete() throws IOException,InterruptedException,URISyntaxException {

		// 获取fs对象
		Configuration conf = new Configuration();
		//TODO:第一个的参数应为真实的服务器信息，第三个参数应为真实服务器用户
		FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), conf, "atguigu");

		// 文件删除
		//TODO:第一个参数是服务器文件或文件夹的路径，第二个参数表示是否要递归删除（如果是文件夹则必须要递归删除其子内容）
		fs.delete(new Path("/test"),true);

		// 关闭资源
		fs.close();

	}

	/**
	 * 更改文件名
	 */
	@Test
	public void rename() throws IOException,InterruptedException,URISyntaxException {

		// 获取fs对象
		Configuration conf = new Configuration();
		//TODO:第一个的参数应为真实的服务器信息，第三个参数应为真实服务器用户
		FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), conf, "atguigu");

		// 文件删除
		//TODO:第一个参数是原文件名（包括路径），第二个参数是新的文件名
		fs.rename(new Path("/test.txt"),new Path("/new.txt"));

		// 关闭资源
		fs.close();

	}

	/**
	 * 查看文件具体信息
	 */
	@Test
	public void listFiles() throws IOException,InterruptedException,URISyntaxException {

		// 获取fs对象
		Configuration conf = new Configuration();
		//TODO:第一个的参数应为真实的服务器信息，第三个参数应为真实服务器用户
		FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), conf, "atguigu");

		// 查看文件详情
		// 1.获取文件
		//TODO:第一个参数是要查询的文件，第二个参数表示是否要递归查询；返回一个迭代器对象
		RemoteIterator<LocatedFileStatus> lists = fs.listFiles(new Path("/"), true);
		// 2.遍历文件
		while(lists.hasNext()){
			LocatedFileStatus file = lists.next();
			//查询文件信息
			System.out.println(file.getPath().getName());	//文件名称
			System.out.println(file.getPermission());	//文件权限
			System.out.println(file.getLen());	//文件长度
			//获取副本信息
			BlockLocation[] blockLocations = file.getBlockLocations();
			for(BlockLocation blockLocation:blockLocations){
				String[] hosts=blockLocation.getHosts();	//副本所在主机名
				for(String host:hosts){
					System.out.println(host);
				}
			}
		}

		// 关闭资源
		fs.close();

	}

	/**
	 * 判断是文件还是文件夹
	 */
	@Test
	public void isFile() throws IOException,InterruptedException,URISyntaxException {

		// 获取fs对象
		Configuration conf = new Configuration();
		//TODO:第一个的参数应为真实的服务器信息，第三个参数应为真实服务器用户
		FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:9000"), conf, "atguigu");

		// 文件删除
		//TODO:参数是要判断的文件
		FileStatus[] fileStatuses = fs.listStatus(new Path("/"));
		for(FileStatus file:fileStatuses){
			if(file.isFile()){			//用isFile方法判断
				System.out.println(file.getPath().getName()+"是文件");
			}else{
				System.out.println(file.getPath().getName()+"是文件夹");
			}
		}

		// 关闭资源
		fs.close();

	}

}
